<template>
  <view class="app-image-preview">
    <!-- 图片网格 -->
    <view class="image-grid" v-if="images && images.length > 0">
      <view 
        v-for="(image, index) in images" 
        :key="image.id || index"
        class="image-item"
        @click="handlePreview(index)"
      >
        <image 
          :src="getImageUrl(image)" 
          mode="aspectFill"
          class="image-preview"
          @error="handleImageError"
          @load="handleImageLoad"
        />
        <view class="image-overlay">
          <u-icon name="eye" color="#fff" size="16"></u-icon>
        </view>
        <!-- 图片信息 -->
        <view v-if="showImageInfo" class="image-info">
          <text class="image-name">{{ getImageName(image) }}</text>
          <text v-if="getImageSize(image)" class="image-size">{{ formatFileSize(getImageSize(image)) }}</text>
        </view>
      </view>
    </view>
    
    <!-- 空状态 -->
    <view v-else class="empty-state">
      <u-icon name="image" size="48" color="#ccc"></u-icon>
      <text class="empty-text">{{ emptyText }}</text>
    </view>
  </view>
</template>

<script setup>
/**
 * App端图片预览组件
 * 生产环境标准实现，支持图片预览、错误处理、加载状态等功能
 * 
 * @author Wu.Liang
 * @date 2025-01-30
 * @version 1.0.0
 */

import { computed } from 'vue'

// Props定义
const props = defineProps({
  // 图片列表
  images: {
    type: Array,
    default: () => []
  },
  // 是否显示图片信息
  showImageInfo: {
    type: Boolean,
    default: false
  },
  // 空状态文本
  emptyText: {
    type: String,
    default: '暂无图片'
  },
  // 图片URL字段名
  urlField: {
    type: String,
    default: 'fileUrl'
  },
  // 图片名称字段名
  nameField: {
    type: String,
    default: 'fileName'
  },
  // 图片大小字段名
  sizeField: {
    type: String,
    default: 'fileSize'
  }
})

// Emits定义
const emit = defineEmits(['preview', 'error', 'load'])

// 计算属性：有效的图片列表
const validImages = computed(() => {
  if (!props.images || !Array.isArray(props.images)) {
    return []
  }
  
  return props.images.filter(image => {
    const url = getImageUrl(image)
    return url && url.trim() !== ''
  })
})

// 获取图片URL
const getImageUrl = (image) => {
  if (!image) return ''
  
  // 支持多种URL字段名
  const url = image[props.urlField] || image.url || image.src || image.fileUrl || ''
  
  // 确保URL是字符串
  return String(url).trim()
}

// 获取图片名称
const getImageName = (image) => {
  if (!image) return ''
  
  const name = image[props.nameField] || image.fileName || image.name || ''
  return String(name).trim() || '未命名图片'
}

// 获取图片大小
const getImageSize = (image) => {
  if (!image) return 0
  
  const size = image[props.sizeField] || image.fileSize || image.size || 0
  return parseInt(size) || 0
}

// 格式化文件大小
const formatFileSize = (fileSize) => {
  if (!fileSize || fileSize === 0) {
    return '0 B'
  }
  
  const units = ['B', 'KB', 'MB', 'GB']
  let size = fileSize
  let unitIndex = 0
  
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex++
  }
  
  return `${size.toFixed(1)} ${units[unitIndex]}`
}

// 处理图片预览
const handlePreview = (index) => {
  try {
    const imageList = validImages.value
    if (!imageList || imageList.length === 0) {
      uni.showToast({
        title: '暂无图片',
        icon: 'none'
      })
      return
    }
    
    // 构建URL列表
    const urls = imageList.map(img => getImageUrl(img))
    const current = urls[index] || urls[0]
    
    // 调用uni.previewImage
    uni.previewImage({
      urls: urls,
      current: current,
      success: () => {
        console.log('图片预览成功，索引:', index)
        emit('preview', { index, image: imageList[index], url: current })
      },
      fail: (error) => {
        console.error('图片预览失败:', error)
        uni.showToast({
          title: '图片预览失败',
          icon: 'none'
        })
        emit('error', { index, image: imageList[index], error })
      }
    })
  } catch (error) {
    console.error('图片预览处理失败:', error)
    uni.showToast({
      title: '图片预览失败',
      icon: 'none'
    })
    emit('error', { index, error })
  }
}

// 处理图片加载错误
const handleImageError = (error) => {
  console.error('图片加载失败:', error)
  emit('error', { error })
}

// 处理图片加载成功
const handleImageLoad = (event) => {
  console.log('图片加载成功:', event)
  emit('load', { event })
}
</script>

<style lang="scss" scoped>
.app-image-preview {
  width: 100%;
}

.image-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  padding: 16px;
}

.image-item {
  position: relative;
  aspect-ratio: 1;
  border-radius: 8px;
  overflow: hidden;
  background: #f5f5f5;
  cursor: pointer;
  transition: transform 0.2s ease;
  
  &:active {
    transform: scale(0.95);
  }
}

.image-preview {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s ease;
  
  .image-item:hover & {
    opacity: 1;
  }
}

.image-info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
  padding: 8px;
  
  .image-name {
    display: block;
    font-size: 12px;
    color: #fff;
    margin-bottom: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  
  .image-size {
    display: block;
    font-size: 10px;
    color: rgba(255, 255, 255, 0.8);
  }
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 16px;
  
  .empty-text {
    margin-top: 12px;
    font-size: 14px;
    color: #999;
  }
}

/* 响应式设计 */
@media screen and (max-width: 375px) {
  .image-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 6px;
    padding: 12px;
  }
}

@media screen and (min-width: 414px) {
  .image-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    padding: 20px;
  }
}
</style>
